import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import qs from 'qs'
import { message } from 'ant-design-vue'

const defaultConfig = {
  timeout: 5000,
  baseUrl: '',
  withCredentials: true
}

/**
 * 返回格式
 */
export interface resDate<T> {
  code: number,
  message: string,
  data: T,
  timestamp: string
}

/**
 * 定义请求拦截以及格式等
 */
class Http {
  constructor() {
    this.httpInterceptorsRequest()
    this.httpInterceptorsResponse()
  }

  // 初始化实例
  private static axiosInstance = axios.create(defaultConfig)

  /**
   * 请求拦截
   */
  private httpInterceptorsRequest() {
    Http.axiosInstance.interceptors.request.use(
      (request: AxiosRequestConfig) => {
        return request
      }, err => {
        return Promise.reject(err)
      }
    )
  }

  /**
   * 响应拦截
   */
  private httpInterceptorsResponse() {
    Http.axiosInstance.interceptors.response.use(
      (response: AxiosResponse) => {
        const data:resDate<any> = response.data
        if (data.code === 0) {
          return response
        } else {
          message.error(data.data + '错误码：' + data.code)
        }
      }, err => {
        // 接收到异常响应
        if (err && err.response) {
          // 根据响应码做公共错误处理
          switch (err.response.status) {
            case 400:
              message.error('错误请求')
              break
            case 401:
              console.log('没有权限')
              message.error('没有权限')
              break
            case 403:
              message.error('拒绝访问')
              break
            case 404:
              message.error('资源未找到')
              // 跳转到404页面
              break
            case 405:
              message.error('请求方法为允许')
              break
            case 408:
              message.error('请求超时')
              break
            case 500:
              message.error('服务器端异常')
              break
            case 501:
              message.error('网络未实现')
              break
            case 502:
              message.error('网络错误')
              break
            case 503:
              message.error('服务不可用')
              break
            case 504:
              message.error('网络超时')
              break
            case 505:
              message.error('http版本不支持该请求')
              break
            default:
              message.error(`连接错误:${err.response.status}`)
          }
        } else {
          // 超时处理
          if (JSON.stringify(err).includes('timeout')) {
            message.error('服务器响应超时，请您刷新当前页面')
          } else {
            message.error('连接服务器失败')
          }
        }
        // 处理结束
        return Promise.reject(err)
      }
    )
  }

  /**
   * 封装get请求
   */
  public doGet<T> (url: string, params: {}) :Promise<T> {
    return new Promise(
      (resolve, reject) => {
        Http.axiosInstance
          .get(url, {
            params
          })
          .then(response => {
            resolve(response.data.result)
          })
          .catch(err => {
            reject(err)
          })
      }
    )
  }

  /**
   * 封装post-form-data请求
   */
  public doPost<T> (url: string, params: {}) :Promise<T> {
    const options = {
      url,
      data: qs.stringify(params),
      method: 'post',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Access-Control-Allow-Origin': '*'
      }
    }
    return new Promise((resolve, reject) => {
      Http.axiosInstance(options).then(
        response => {
          resolve(response.data.data)
        },
        err => {
          reject(err)
        }
      )
    })
  }

  /**
   * 封装post-json请求
   */
  public doPostJson<T> (url: string, params: {}) :Promise<T> {
    const options = {
      url,
      data: JSON.stringify(params),
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      }
    }
    return new Promise((resolve, reject) => {
      Http.axiosInstance(options)
        .then(res => {
          resolve(res.data.data)
        })
        .catch(err => {
          reject(err)
        })
    })
  }

  /**
   * 封装put-form-data请求
   */
  public doPut<T> (url: string, params: {}) :Promise<T> {
    const options = {
      url,
      data: qs.stringify(params),
      method: 'put',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Access-Control-Allow-Origin': '*'
      }
    }
    return new Promise((resolve, reject) => {
      Http.axiosInstance(options).then(
        response => {
          resolve(response.data.data)
        },
        err => {
          reject(err)
        }
      )
    })
  }

  /**
   * 封装put-json请求
   */
  public doPutJson<T> (url: string, params: {}) :Promise<T> {
    const options = {
      url,
      data: JSON.stringify(params),
      method: 'put',
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      }
    }
    return new Promise((resolve, reject) => {
      Http.axiosInstance(options)
        .then(res => {
          resolve(res.data.data)
        })
        .catch(err => {
          reject(err)
        })
    })
  }

  /**
   * 封装del-form-data请求
   */
  public doDel<T> (url: string, params: {}) :Promise<T> {
    const options = {
      url,
      data: qs.stringify(params),
      method: 'delete',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Access-Control-Allow-Origin': '*'
      }
    }
    return new Promise((resolve, reject) => {
      Http.axiosInstance(options).then(
        response => {
          resolve(response.data.data)
        },
        err => {
          reject(err)
        }
      )
    })
  }
}

export const http = new Http()
